home *** CD-ROM | disk | FTP | other *** search
- /*
- * CopyINIT - an INIT which prevents the copying of resource forks
- * to or from the boot disk by the Finder by intercepting the PBOpenRF
- * trap.
- * It is intended for installation on the hard disks of Macs in public
- * labs.
- * Created and placed in the public domain by Dale Talcott,
- * Purdue University Computing Center, 1989
- */
-
- #include <string.h>
-
- #ifndef NULL
- #define NULL 0
- #endif
- #define OUR_ERROR vLckdErr /* error when we reject operation */
- #define OUR_ID 6500 /* id for resources */
- #define OUR_TRAP_NO 0xa /* PBOpenRF trap number */
-
- #define ZERO(s) memset ((char *)&(s), 0, sizeof (s)) /* zero struct */
-
- /*
- *=========================================================================
- * Globals
- *=========================================================================
- */
- int BootVRefNum; /* vRefNum of boot drive */
- long Orig_trap; /* original trap handler address */
- Handle Our_DITL_hdl; /* handle to DITL */
- Rect Our_rect; /* dialog window rectangle */
-
-
- /*
- *=========================================================================
- * Prototypes
- *=========================================================================
- */
- extern OSErr checkFile(HParmBlkPtr, Ptr);
- extern OSErr gripe(void);
- extern void main(Handle, long);
- extern void trap(void);
-
-
-
- /*
- *======================================================================
- * trap() - the code which is given control on a PBOpenRF trap.
- * entry: at first byte by INIT 31, a0 = handle to selves.
- * at @1 from trap dispatcher
- * returns: nothing if INIT 31,
- * else for trap:
- * OSErr if open not permitted, else
- * exits via original PBOpenRF routine
- *======================================================================
- */
- void
- trap()
- {
- asm {
- /*
- * Start of INIT code
- */
- @0:
- move.l a4,-(sp) /* save a4 */
- lea @0,a4 /* set up global ptr */
- pea @1 /* set trap addr as second arg */
- move.l a0,-(sp) /* put handle as first arg */
- jsr main
- addq #8,sp /* discard args */
- move.l (sp)+,a4 /* restore a4 */
- rts
-
- /*
- * Start of trap code
- */
- @1:
- move.l a6,-(sp) /* fake link, part 1 (for debugger) */
- movem.l d0-d7/a0-a6,-(sp) /* save regs */
- lea 15*4(a7),a6 /* second half of link */
- lea trap,a4 /* set up global ptr */
- /*
- * Check whether to object or to pass to original trap handler.
- * We object if:
- * The current application is "Finder"
- * and the call is not from ROM and
- * CurrentA5 indicates an application is active
- */
- move.l CurApName,d1 /* Check for Finder */
- cmpi.l #'\006Fin',d1
- bne.s @60
- move.l CurApName+4,d1
- clr.b d1
- cmpi.l #'der\000',d1
- bne.s @60
-
- move.l 4(a6),d1 /* our return address */
- moveq #8*4,d2 /* stack offset for trapper addr */
- cmp.l ROMBase,d1 /* check if called from ROM dispatch*/
- bge.s @3 /* if so, trapper addr okay */
- addq #4,d2 /* MultiFinder adds extra layer */
- @3:
- move.l 0(a6,d2.w),d2 /* fetch trapper return addr */
- cmp.l ROMBase,d2
- bge.s @60 /* if called from ROM, okay */
-
- movea.l CurrentA5,a2 /* Check for application */
- cmpa.l #0,a2
- beq.s @60
- move.l (a2),d1
- beq.s @60
- /*
- * Probably will object, let checkFile be the final arbiter
- */
- move.l d1,-(sp) /* arg2 = caller addr */
- move.l a0,-(sp) /* arg1 = caller arg = PB addr */
- jsr checkFile
- addq #8,sp
-
- /*
- * If checkFile returns 0, the call is okay,
- * otherwise we should pass the return value back to the caller
- */
- ext.l d0
- beq.s @60
- addq #4,sp /* discard original d0 */
- movem.l (sp)+,d1-d7/a0-a6
- addq #4,sp /* discard link word */
- rts /* exit to caller (via dispatcher) */
-
- /*
- * Here to pass call on to original trap handler
- */
- @60:
- move.l Orig_trap,(a6) /* replace link word with trap addr */
- movem.l (sp)+,d0-d7/a0-a6
- rts /* branch to handler */
- }
- /*NOTREACHED*/
- }
-
-
- /*
- *=========================================================================
- * checkFile(p,a) - see if we should object to file whose resource fork
- * is being opened
- * entry: p = pointer to paramblock
- * a = caller return address
- * exit: returns 0 if file okay.
- * returns <>0 if file not okay or on OS error
- *=========================================================================
- */
- OSErr
- checkFile (PBp, addr)
- register HParmBlkPtr PBp;
- Ptr addr;
- {
- HParamBlockRec ourPB; /* local copy of paramblock */
- OSErr error;
- register long ftype;
- register long fcreator;
-
- /*
- * See if file is on boot drive. If not, let it go.
- */
- if (PBp->ioParam.ioVRefNum != BootVRefNum)
- return 0;
- /*
- * Look up info about the file.
- */
- ourPB = *PBp;
- ourPB.fileParam.ioCompletion = 0;
- ourPB.fileParam.ioFDirIndex = 0;
- error = PBHGetFInfo (&ourPB, FALSE);
- if (error) {
- if (error == fnfErr)
- error = 0;
- return error;
- }
- /*
- * Check for allowed file types. These can always be opened.
- */
- ftype = ourPB.fileParam.ioFlFndrInfo.fdType;
- fcreator = ourPB.fileParam.ioFlFndrInfo.fdCreator;
- if (ftype == 'TEXT'
- || ftype == 'PICT'
- )
- return 0;
- /*
- * Check for disallowed types or creators. These are the ones
- * we are worried about.
- */
- if (ftype != 'APPL'
- && ftype != 'INIT'
- && ftype != 'ZSYS'
- && ftype != 'cdev'
- && fcreator != 'MACS'
- )
- return 0;
- return (gripe());
- }
-
-
- /*
- *=========================================================================
- * gripe() - Display modal dialog warning that copying not permitted
- *=========================================================================
- */
- OSErr
- gripe()
- {
- Handle ditlh; /* handle to DITL */
- register DialogPtr dp;
- OSErr error;
- register Handle h; /* temp handle */
- short itemHit; /* for dialogs */
- Str255 title;
-
- /*
- * make a copy of our DITL (because DisposDialog() frees it)
- * then build a dialog from it and let ModalDialog handle it
- * thereafter.
- */
- title[0] = 0;
- itemHit = 0;
- ditlh = Our_DITL_hdl;
- if ((error = HandToHand(&ditlh)) == 0) {
- dp = NewDialog (
- (DialogPeek)NULL, /* storage */
- &Our_rect, /* bounds rect */
- title, /* title */
- TRUE, /* visible */
- dBoxProc, /* window type */
- (WindowPtr)-1, /* behind window */
- FALSE, /* goaway box */
- 0l, /* refCon */
- ditlh); /* item list */
-
- if (dp) {
- while (itemHit != 1) {
- ModalDialog ((ProcPtr) NULL, &itemHit);
- }
- DisposDialog (dp);
- }
- }
- if (error == 0 && (error = MemError ()) == 0)
- error = OUR_ERROR;
- return (error);
- }
-
-
- /*
- *=========================================================================
- * main - the code executed during startup
- *=========================================================================
- */
- void
- main(self, addr)
- Handle self;
- long addr;
- {
- register Handle h; /* general temp handle */
- long len; /* length of trap code */
- register Ptr p; /* general temp pointer */
- WDPBRec pb; /* for getting boot vRefNum */
-
- HLock (self);
- /*
- * Check environment. Exit silently if not kosher.
- */
- if (FSFCBLen == -1) /* must have HFS */
- goto exit;
- /*
- * Get and save vRefNum of boot drive
- */
- ZERO(pb);
- pb.ioVRefNum = BootDrive;
- if (PBGetWDInfo (&pb, FALSE) != 0)
- goto exit;
- BootVRefNum = pb.ioWDVRefNum;
- /*
- * Load our DLOG resource, extract the bounding rect, and then
- * purge the resource, since the DLOG exists only to make building
- * the dialog via ResEdit, et al easier.
- */
- h = GetResource ('DLOG', OUR_ID);
- if (h == 0 || ResError())
- goto exit;
- Our_rect = (*(DialogTHndl)h)->boundsRect;
- ReleaseResource (h);
- /*
- * Get our DITL and save its pointer
- */
- h = GetResource ('DITL', OUR_ID);
- if (h == 0 || ResError())
- goto exit;
- Our_DITL_hdl = h;
- /*
- * Allocate nonrelocatable block on system heap for trap code
- */
- len = SizeResource(self);
- asm {
- move.l len,d0
- NewPtr SYS
- move.l a0,p
- }
- if (p == NULL)
- goto exit;
- /*
- * Save original trap address
- */
- Orig_trap = GetTrapAddress (OUR_TRAP_NO);
-
- DetachResource (h);
- /*
- * copy the trap routines to the block
- */
- BlockMove (*self, p, len);
- /*
- * Now that everything is set correctly, set the new code as the
- * trap handler
- */
- addr = (long) (p + (((Ptr)addr - *self) & 0xffff));
- SetTrapAddress (addr, OUR_TRAP_NO);
-
- exit:
- HUnlock (self);
- }